package com.persagy.core.quartz;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Service;

import com.persagy.ems.pojo.quartz.ScheduleJob;

//@Service("ScheduleFactory")
public class ScheduleFactory {

	/*
	 * 之前初始化的是 SchedulerFactoryBean schedulerFactoryBean； 注入报下面的错 nested
	 * exception is
	 * org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean
	 * named 'schedulerFactoryBean' must be of type
	 * [org.springframework.scheduling.quartz.SchedulerFactoryBean], but was
	 * actually of type [org.quartz.impl.StdScheduler>]
	 */
	@Resource
	private Scheduler scheduler;

	/**
	 * 添加一个定时任务
	 * @param job
	 * @param jobAction
	 * @throws Exception 
	 */
	public void registerJob(ScheduleJob job, Class<? extends Job> jobAction) throws Exception {
		if (job == null || job.getJobName() == null) {
			throw new Exception("jobName can not be null!");
		}
		if (job.getJobGroup() == null) {
			throw new Exception("jobGroup can not be null!");
		}
		if (job == null || job.getCronExpression() == null) {
			throw new Exception("cronExpression can not be null!");
		}
		TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
		// 获取trigger
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		// 不存在，创建一个
		if (null == trigger) {
			JobDetail jobDetail = JobBuilder.newJob(jobAction).withIdentity(job.getJobName(), job.getJobGroup()).build();
			jobDetail.getJobDataMap().put("scheduleJob", job);
			// 表达式调度构建器
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
			// 按新的cronExpression表达式构建一个新的trigger
			trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup())
					.withSchedule(scheduleBuilder).build();
			scheduler.scheduleJob(jobDetail, trigger);
		} else {
			// Trigger已存在，那么更新相应的定时设置
			// 表达式调度构建器
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
			// 按新的cronExpression表达式重新构建trigger
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
			// 按新的trigger重新设置job执行
			scheduler.rescheduleJob(triggerKey, trigger);
		}
	}


	/**
	 * 获取正在运行或计划运行的全部任务
	 * @return
	 * @throws SchedulerException
	 */
	public List<ScheduleJob> getScheduleJobs() throws SchedulerException {
		GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
		Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
		List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
		for (JobKey jobKey : jobKeys) {
			List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
			for (Trigger trigger : triggers) {
				ScheduleJob job = new ScheduleJob();
				job.setJobName(jobKey.getName());
				job.setJobGroup(jobKey.getGroup());
				Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
				job.setJobCurrentStatus(triggerState.name());
				if (trigger instanceof CronTrigger) {
					CronTrigger cronTrigger = (CronTrigger) trigger;
					String cronExpression = cronTrigger.getCronExpression();
					job.setCronExpression(cronExpression);
				}
				jobList.add(job);
			}
		}
		return jobList;
	}

	/**
	 * 获取运行中的任务
	 * @return
	 * @throws SchedulerException
	 */
	public List<ScheduleJob> getRunningJobs() throws SchedulerException {
		List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
		List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());
		for (JobExecutionContext executingJob : executingJobs) {
			ScheduleJob job = new ScheduleJob();
			JobDetail jobDetail = executingJob.getJobDetail();
			JobKey jobKey = jobDetail.getKey();
			Trigger trigger = executingJob.getTrigger();
			job.setJobName(jobKey.getName());
			job.setJobGroup(jobKey.getGroup());
			Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
			job.setJobCurrentStatus(triggerState.name());
			if (trigger instanceof CronTrigger) {
				CronTrigger cronTrigger = (CronTrigger) trigger;
				String cronExpression = cronTrigger.getCronExpression();
				job.setCronExpression(cronExpression);
			}
			jobList.add(job);
		}
		return jobList;
	}

	/**
	 * 暂停任务
	 * @param job
	 * @throws Exception 
	 */
	public void pauseJob(ScheduleJob job) throws Exception {
		if (job == null || job.getJobName() == null) {
			throw new Exception("jobName can not be null!");
		}
		if (job.getJobGroup() == null) {
			throw new Exception("jobGroup can not be null!");
		}
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		scheduler.pauseJob(jobKey);
	}

	/**
	 * 恢复任务
	 * @param job
	 * @throws Exception 
	 */
	public void resumeJob(ScheduleJob job) throws Exception {
		if (job == null || job.getJobName() == null) {
			throw new Exception("jobName can not be null!");
		}
		if (job.getJobGroup() == null) {
			throw new Exception("jobGroup can not be null!");
		}
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		scheduler.resumeJob(jobKey);
	}

	/**
	 * 删除任务
	 * @param job
	 * @throws Exception 
	 */
	public void deleteJob(ScheduleJob job) throws Exception {
		if (job == null || job.getJobName() == null) {
			throw new Exception("jobName can not be null!");
		}
		if (job.getJobGroup() == null) {
			throw new Exception("jobGroup can not be null!");
		}
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		scheduler.deleteJob(jobKey);
	}

	/**
	 * 立刻触发job运行
	 * @param job
	 * @throws Exception 
	 */
	public void triggerJob(ScheduleJob job) throws Exception {
		if (job == null || job.getJobName() == null) {
			throw new Exception("jobName can not be null!");
		}
		if (job.getJobGroup() == null) {
			throw new Exception("jobGroup can not be null!");
		}
		JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
		scheduler.triggerJob(jobKey);
	}

	/**
	 * 更新任务时间表达式
	 * @param job
	 * @throws Exception 
	 */
	public void updateJob(ScheduleJob job) throws Exception {
		if (job == null || job.getJobName() == null) {
			throw new Exception("jobName can not be null!");
		}
		if (job.getJobGroup() == null) {
			throw new Exception("jobGroup can not be null!");
		}
		if (job.getCronExpression() != null) {
			TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			if (trigger != null) {
				// 表达式调度构建器
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
				// 按新的cronExpression表达式重新构建trigger
				trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
				// 按新的trigger重新设置job执行
				scheduler.rescheduleJob(triggerKey, trigger);
			}
		}
	}
	
	/**
     * 获取job信息
     * @param scheduler
     * @param jobName
     * @param jobGroup
     * @return
     * @throws SchedulerException
     */
    public JobDetail getJobDetail(String jobName, String jobGroup) throws Exception {
        JobKey jobKey = new JobKey(jobName, jobGroup);;
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        return jobDetail;
    }
	
	public String getJobStatus(ScheduleJob job) throws Exception {
		TriggerKey jobKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
		return scheduler.getTriggerState(jobKey).name();
	}

}